import * as THREE from 'three';
const vertexShader = `
  uniform float size;
  uniform float scale;
  varying float opacity;
  void main() {
    vec4 mPosition = modelMatrix * vec4( position, 1.0 );
    vec4 mvPosition = viewMatrix * mPosition;
    vec4 mZeroPositon = modelMatrix * vec4(.0, .0, .0, 1.0);
    vec3 positionToZero = mPosition.xyz - mZeroPositon.xyz;
    vec3 vToEye = cameraPosition - mPosition.xyz;
    opacity = dot(vToEye, positionToZero);
    gl_PointSize = size * ( scale / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
  }
`;
const fragmentShader = `
  uniform vec3 color;
  uniform sampler2D pointTexture;
  varying float opacity;
  void main() {
    if(opacity <= 0.0) {
      gl_FragColor = vec4(color, 0.05);
    } else {
      gl_FragColor = vec4(color, 1.0);
    }
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  }
`;

// 科技感地球 TechnologyEarth
export default class {
  mesh = new THREE.Group();
  earth = new THREE.Group();
  textureLoader = new THREE.TextureLoader();
  height: 1080;
  devicePixelRatio: 1;
  config = {
    defaultConfig: {
      pointImage: 'dot.png',
      borderImage: 'opacityMap.png',
      mapImage: 'map_inverted3.jpg'
    },
    pointConfig: {
      color: '#3c5e7c',
      size: 22,
      count: 200
    },
    lineConfig: {
      show: true,
      color: '#5e8db6',
      opacity: 1
    }
  };
  constructor() {
    this.initPointsMaterial();
    this.showPoints();
    if (this.config.lineConfig.show) {
      this.initBorderMaterial();
      this.showBorder();
    }
    return this;
  }
  rotate() {
    this.mesh.rotateY(0.001);
  }
  showPoints() {
    var image = document.createElement('img');
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = this.config.defaultConfig.mapImage;
    image.onload = () => {
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      canvas.width = image.width;
      canvas.height = image.height;
      ctx.drawImage(image, 0, 0, image.width, image.height);
      this.earthImgData = ctx.getImageData(0, 0, image.width, image.height);
      this.createEarthParticles(this.earthImgData, image.width, image.height);
    };
  }
  showBorder() {
    this.border = new THREE.Mesh(new THREE.SphereGeometry(1e3, 128, 128), this.borderMaterial);
    this.showGroup.add(this.border);
  }
  initPointsMaterial() {
    const option = {
      scale: (this.config.height / 2) * this.config.devicePixelRatio,
      color: new THREE.Color(this.config.pointConfig.color),
      pointTexture: this.textureLoader.load(this.config.defaultConfig.pointImage),
      size: this.config.pointConfig.size,
      radius: 1e3
    }
    this.pointsMaterial = new THREE.ShaderMaterial({
      uniforms: ,
      transparent: true,
      depthTest: false,
      blending: THREE.AdditiveBlending,
      vertexShader: this.vertexShader,
      fragmentShader: this.fragmentShader,
      alphaTest: 0.8
    });
  }
  initBorderMaterial() {
    this.borderMaterial = new THREE.MeshBasicMaterial({
      color: new THREE.Color(this.config.lineConfig.color.toLocaleLowerCase()),
      map: this.textureLoader.load(this.config.defaultConfig.borderImage),
      transparent: true,
      blending: THREE.AdditiveBlending,
      depthTest: false,
      opacity: this.config.lineConfig.opacity
    });
  }
  createEarthParticles(e, t, a) {
    var i = [];
    var r = new THREE.Spherical();
    r.radius = 1e3;
    var o = this.config.pointConfig.count;
    for (var s = 0; s < o; s++) {
      var l = new THREE.Vector3();
      var u = 1 / Math.cos((Math.abs(s - o / 2) / o) * Math.PI);
      for (var c = 0; c < o; c += u) {
        var h = c / o;
        var p = s / o;
        Math.floor(2 * Math.random());
        if (this.isLandByUV(h, p, e, t, a)) {
          r.theta = h * Math.PI * 2 - Math.PI / 2;
          r.phi = p * Math.PI;
          l.setFromSpherical(r);
          i.push(l.x, l.y, l.z);
        }
      }
      l = null;
    }
    var d = new THREE.BufferGeometry();
    d.setAttribute('position', new THREE.Float32BufferAttribute(i, 3));
    d.computeBoundingSphere();
    this.points = new THREE.Points(d, this.pointsMaterial);
    this.points.renderOrder = 3;
    this.showGroup.add(this.points);
    i = null;
  }
  isLandByUV(e, t, a, n, i) {
    if (!a) {
      console.error('data error!');
    }
    var r = parseInt(n * e);
    var o = parseInt(i * t);
    return 100 < a.data[4 * (o * a.width + r)];
  }
  updateComponent(e) {
    var a = this.config.pointConfig;
    var n = this.config.lineConfig;
    this.config = e.configuration.technologyEarth;
    var r = this.config.pointConfig;
    var o = this.config.lineConfig;
    if (!(r.size === a.size && r.color === a.color)) {
      this.pointsMaterial.uniforms.size.value = r.size;
      this.pointsMaterial.uniforms.color.value = new b.Color(r.color);
    }
    if (!(o.color === n.color && o.opacity === n.opacity)) {
      this.borderMaterial.color = new b.Color(o.color);
      this.borderMaterial.opacity = o.opacity;
    }
    if (r.count !== a.count) {
      this.points && this.points.geometry && this.points.geometry.dispose();
      this.showGroup.remove(this.points);
      this.points = null;
      this.showPoints();
    }
    if (o.show !== n.show) {
      this.destroyBorder();
      if (o.show) {
        this.initBorderMaterial();
        this.showBorder();
      }
    }
  }
  destroyPoints() {
    this.points && this.points.geometry && this.points.geometry.dispose();
    this.pointsMaterial && this.pointsMaterial.map && this.pointsMaterial.map.dispose();
    this.pointsMaterial && this.pointsMaterial.dispose();
    this.showGroup.remove(this.points);
    this.pointsMaterial && (this.pointsMaterial.map = null);
    this.pointsMaterial = null;
    this.points = null;
  }
  destroyBorder() {
    this.border && this.border.geometry && this.border.geometry.dispose();
    this.borderMaterial && this.borderMaterial.map && this.borderMaterial.map.dispose();
    this.borderMaterial && this.borderMaterial.dispose();
    this.showGroup.remove(this.border);
    this.borderMaterial && (this.borderMaterial.map = null);
    this.borderMaterial = null;
    this.border = null;
  }
  destroy() {
    this.textureLoader = null;
    this.earthImgData = null;
    this.destroyPoints();
    this.destroyBorder();
    this.earthGroup.remove(this.showGroup);
    this.showGroup = null;
  }
}
